package com.zhibang.controller;

import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.json.JsonData;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.zhibang.dto.HotelDTO;
import com.zhibang.entity.GroupTravel;
import com.zhibang.entity.TbHotel;
import com.zhibang.util.Result;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.annotation.Resource;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.client.elc.NativeQuery;
import org.springframework.data.elasticsearch.client.elc.NativeQueryBuilder;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.HighlightQuery;
import org.springframework.data.elasticsearch.core.query.highlight.Highlight;
import org.springframework.data.elasticsearch.core.query.highlight.HighlightField;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

/**
 * @autor yy
 * @date 2025年07月02日09:43
 */
@RestController
@RequestMapping("Hotel")
public class HotelController {
    @Resource
    ElasticsearchTemplate template;
    @RequestMapping("search")
    @Operation(summary = "酒店搜索")
    public Result search(@RequestBody HotelDTO dto) {
        // 1. 创建查询对象
        BoolQuery.Builder builder = new BoolQuery.Builder();
        // 2. 判断搜索框
        if (StringUtils.isNotBlank(dto.getKey())) {
            builder.must(m -> m.queryString(qs -> qs.query(dto.getKey())));
        }
        if (StringUtils.isNotBlank(dto.getBrand())) {
            builder.must(m -> m.term(qs -> qs.field("brand").value(dto.getBrand())));
        }
        if (StringUtils.isNotBlank(dto.getCity())) {
            builder.must(m -> m.term(qs -> qs.field("city").value(dto.getCity())));
        }
        if (StringUtils.isNotBlank(dto.getStarName())) {
            builder.must(m -> m.term(qs -> qs.field("starName").value(dto.getStarName())));
        }
        if(dto.getMinPrice() != null){
            builder.must(m->m.range(qs->qs.field("price").gte(JsonData.of(dto.getMinPrice()))));
        }
        if(dto.getMaxPrice() != null){
            builder.must(m->m.range(qs->qs.field("price").lte(JsonData.of(dto.getMaxPrice()))));
        }
        // 高亮设置
        HighlightField field = new HighlightField("*");
        Highlight highlight = new Highlight(List.of(field));
        HighlightQuery highlightQuery = new HighlightQuery(highlight, TbHotel.class);
        // 查询构造器
        NativeQueryBuilder nativeQueryBuilder = NativeQuery.builder()
                .withQuery(builder.build()._toQuery())
                .withPageable(PageRequest.of(dto.getPage() - 1, dto.getSize()))
                .withHighlightQuery(highlightQuery);
        // 排序
        if("level".equals(dto.getSortBy())){
            nativeQueryBuilder.withSort(s->s.field(
                    filed->filed.field("level").order(SortOrder.Desc)
            ));
        }
        if("price".equals(dto.getSortBy())){
            nativeQueryBuilder.withSort(s->s.field(
                    filed->filed.field("price").order(SortOrder.Asc)
            ));
        }
        if("score".equals(dto.getSortBy())){
            nativeQueryBuilder.withSort(s->s.field(
                    filed->filed.field("score").order(SortOrder.Desc)
            ));
        }
        // 查询
        SearchHits<TbHotel> searchHits = template.search(nativeQueryBuilder.build(), TbHotel.class);
        List<TbHotel> docs = new ArrayList<>();
        for (SearchHit<TbHotel> searchHit : searchHits) {
            TbHotel doc = searchHit.getContent();
            // 获取高亮结果
            searchHit.getHighlightFields().forEach((k,v)->{
                if("name".equals(k)) doc.setName(v.get(0));
            });
            docs.add(doc);
        }
        // 创建返回数据
        JSONObject result = new JSONObject();
        result.put("page",dto.getPage());
        result.put("pageSize",dto.getSize());
        result.put("total",searchHits.getTotalHits());
        result.put("data",docs);
        return Result.data(result);
    }
}